package com.beemindz.miyotee.activity;

import java.util.ArrayList;
import java.util.Calendar;

import org.apache.commons.lang3.StringUtils;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

import com.beemindz.miyotee.R;
import com.beemindz.miyotee.activity.adapter.TaskListAdapter;
import com.beemindz.miyotee.activity.navigation.ItemAdapter;
import com.beemindz.miyotee.activity.navigation.ItemNavigation;
import com.beemindz.miyotee.provider.MyToDo;
import com.beemindz.miyotee.provider.Task;
import com.beemindz.miyotee.provider.TaskHelper;
import com.beemindz.miyotee.utils.CommonUtils;
import com.beemindz.miyotee.utils.Constant;
import com.beemindz.miyotee.utils.ToastUtils;

@SuppressLint("NewApi")
public class TaskListActivity extends ListActivity {

  // For logging and debugging
  private static final String TAG = "TasksListActivity";

  Button btnAddTask;
  EditText etTitle;
  MenuItem menuSignOut, menuSync;
  private DrawerLayout mDrawerLayout;
  private ListView mleftList;
  private ActionBarDrawerToggle mDrawerToggle;
  private ArrayList<ItemNavigation> arrLeft, arrRight;

  private static final String[] TASK_PROJECTION = new String[] { MyToDo.Tasks._ID, MyToDo.Tasks.COLUMN_NAME_ID,
      MyToDo.Tasks.COLUMN_NAME_NAME, MyToDo.Tasks.COLUMN_NAME_DESCRIPTION, MyToDo.Tasks.COLUMN_NAME_REMINDER_DATE,
      MyToDo.Tasks.COLUMN_NAME_CREATE_DATE, MyToDo.Tasks.COLUMN_NAME_UPDATE_DATE };

  private Account[] accounts;
  private TaskListAdapter taskListAdapter;
  private ArrayList<Task> tasks;
  private TaskHelper taskHelper;
  private Uri mUri;

  /**
   * The index of the TaskId column
   */
  private static final int COLUMN_INDEX_NAME = 2;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_task_list);

    taskHelper = new TaskHelper(this);
    tasks = new ArrayList<Task>();

    btnAddTask = (Button) findViewById(R.id.btnAddTask);
    etTitle = (EditText) findViewById(R.id.etTitle);
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mleftList = (ListView) findViewById(R.id.left_drawer);

    // Add data to array navigation menu
    initArrayForListViewDrawer();
    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);

    accounts = AccountManager.get(this).getAccountsByType(Constant.ACCOUNT_TYPE);
    if (accounts.length == 0) {
      // Intent intent = new Intent(this, MainActivity.class);
      // startActivity(intent);
    } else {
    }

    // The user does not need to hold down the key to use menu shortcuts.
    setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);

    /*
     * If no data is given in the Intent that started this Activity, then this Activity was started when the intent
     * filter matched a MAIN action. We should use the default provider URI.
     */
    // Gets the intent that started this Activity.
    final Intent intent = getIntent();

    // If there is no data associated with the Intent, sets the data to the
    // default URI, which
    // accesses a list of tasks.
    if (intent.getData() == null) {
      intent.setData(MyToDo.Tasks.CONTENT_URI);
    }

    /*
     * Sets the callback for context menu activation for the ListView. The listener is set to be this Activity. The
     * effect is that context menus are enabled for items in the ListView, and the context menu is handled by a method
     * in NotesList.
     */
    getListView().setOnCreateContextMenuListener(this);

    mUri = intent.getData();

    btnAddTask.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View arg0) {
        String title = etTitle.getText().toString().trim();
        if (StringUtils.isNotBlank(title)) {
          mUri = getContentResolver().insert(intent.getData(), null);
          updateTask(title, "", "");
          updateData();
          etTitle.setText("");
        }
      }
    });

    // event navigaiont menu Left
    navigationMenuOnClickLeft();

    // set data to list view.
    updateData();
  }

  /* _-----NAVIGATION MENU----- */
  private void navigationMenuOnClickLeft() {
    mleftList.setOnItemClickListener(new OnItemClickListener() {

      @Override
      public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
        switch (pos) {
        case 0:
          // redirect to activity settings
          Intent i = new Intent(getApplicationContext(), SettingActivity.class);
          startActivity(i);
          break;
        default:
          break;
        }

        Log.d("debug", "click left " + pos);
        mleftList.setItemChecked(pos, true);
        // Dong Drawer khi click xong
        mDrawerLayout.closeDrawer(mleftList);

      }
    });

    // Set Adapter cho list ben trai
    ItemAdapter adapterLeft = new ItemAdapter(this, arrLeft);
    mleftList.setAdapter(adapterLeft);

    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    mDrawerToggle = new ActionBarDrawerToggle(this, /* Activity chua Actionbar */
    mDrawerLayout, /* DrawerLayout de lien ket den ActionBar */
    R.drawable.ic_drawer, /* Hinh anh Drawer */
    R.string.drawer_open, /* Chuoi mo ta hanh dong mo Drawer "open drawer" */
    R.string.drawer_close /* Chuoi mo ta hanh dong dong Drawer "close drawer" */
    ) {
      public void onDrawerClosed(View view) {
        getActionBar().setTitle(getResources().getString(R.string.app_name));
        Log.d("debug", "onDrawerClosed");
        invalidateOptionsMenu(); // tao lai menu sau khi options menu da duoc thay doi
      }

      public void onDrawerOpened(View drawerView) {
        getActionBar().setTitle(getResources().getString(R.string.drawer_open));
        Log.d("debug", "onDrawerOpened");
        invalidateOptionsMenu();
      }
    };

    mDrawerLayout.setDrawerListener(mDrawerToggle);
  }

  // Them du lieu vao array
  private void initArrayForListViewDrawer() {
    // TODO Auto-generated method stub
    arrLeft = new ArrayList<ItemNavigation>();
    arrRight = new ArrayList<ItemNavigation>();

    ItemNavigation ItemNavigation1 = new ItemNavigation(R.drawable.ic_action_settings, getResources().getString(
        R.string.sign_up_to_sync));
    arrLeft.add(ItemNavigation1);
    ItemNavigation ItemNavigation5 = new ItemNavigation(R.drawable.ic_action_about, getResources().getString(
        R.string.about));
    arrLeft.add(ItemNavigation5);
  }

  @Override
  public boolean onPrepareOptionsMenu(Menu menu) {
    // If the nav drawer is open, hide action items related to the content
    // view
    Log.d("debug", "onPrepareOptionsMenu");
    // Neu drawer ben trai dang mo thi an cac item cua actionbar
    boolean drawerleftOpen = mDrawerLayout.isDrawerOpen(mleftList);
    menu.findItem(R.id.action_sign_out).setVisible(!drawerleftOpen);
    menu.findItem(R.id.action_sync).setVisible(!drawerleftOpen);
    menu.findItem(R.id.action_insert).setVisible(!drawerleftOpen);

    return super.onPrepareOptionsMenu(menu);
  }

  @Override
  protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    Log.d("debug", "onPostCreate");
    mDrawerToggle.syncState();
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // Pass any configuration change to the drawer toggls
    Log.d("debug", "onConfigurationChanged");
  }

  /* _-----END NAVIGATION MENU----- */

  private void updateData() {
    taskHelper = new TaskHelper(this);
    tasks = taskHelper.loadAllTask();

    // set value into list view task
    taskListAdapter = new TaskListAdapter(this, tasks);

    // Sets the ListView's adapter to be the cursor adapter that was just
    // created.
    setListAdapter(taskListAdapter);
  }

  private final void updateTask(String name, String description, String reminderDate) {

    // Sets up a map to contain values to be updated in the provider.
    ContentValues values = new ContentValues();
    Account[] accounts = AccountManager.get(this).getAccountsByType(Constant.ACCOUNT_TYPE);
    if (accounts.length > 0) {
      values.put(MyToDo.Tasks.COLUMN_NAME_USER_NAME, accounts[0].name);
    }
    values.put(MyToDo.Tasks.COLUMN_NAME_UPDATE_DATE,
        CommonUtils.getStringDate(Calendar.getInstance(), Constant.DATE_TIME_FORMAT));
    values.put(MyToDo.Tasks.COLUMN_NAME_NAME, name);
    values.put(MyToDo.Tasks.COLUMN_NAME_DESCRIPTION, description);
    values.put(MyToDo.Tasks.COLUMN_NAME_REMINDER_DATE, reminderDate);

    getContentResolver().update(mUri, values, null, null);
  }

  @Override
  protected void onResume() {
    super.onResume();
    if (getListView() != null) {
      updateData();
    }
  }

  /**
   * Called when the user clicks the device's Menu button the first time for this Activity. Android passes in a Menu
   * object that is populated with items. Sets up a menu that provides the Insert option plus a list of alternative
   * actions for this Activity. Other applications that want to handle notes can "register" themselves in Android by
   * providing an intent filter that includes the category ALTERNATIVE and the mimeTYpe MyToDo.Tasks.CONTENT_TYPE. If
   * they do this, the code in onCreateOptionsMenu() will add the Activity that contains the intent filter to its list
   * of options. In effect, the menu will offer the user other applications that can handle notes.
   * 
   * @param menu A Menu object, to which menu items should be added.
   * @return True, always. The menu should be displayed.
   */
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate menu from XML resource
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.task_list, menu);

    // Generate any additional actions that can be performed on the
    // overall list. In a normal install, there are no additional
    // actions found here, but this allows other applications to extend
    // our menu with their own actions.
    Intent intent = new Intent(null, getIntent().getData());
    intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
    menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, new ComponentName(this, TaskListActivity.class), null,
        intent, 0, null);

    return super.onCreateOptionsMenu(menu);
  }

  /**
   * This method is called when the user selects an option from the menu, but no item in the list is selected. If the
   * option was INSERT, then a new Intent is sent out with action ACTION_INSERT. The data from the incoming Intent is
   * put into the new Intent. In effect, this triggers the NoteEditor activity in the NotePad application. If the item
   * was not INSERT, then most likely it was an alternative option from another application. The parent method is called
   * to process the item.
   * 
   * @param item The menu item that was selected by the user
   * @return True, if the INSERT menu item was selected; otherwise, the result of calling the parent method.
   */
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    switch (id) {
    case android.R.id.home:
      Log.d("debug", "click home");
      boolean drawerleftOpen = mDrawerLayout.isDrawerOpen(mleftList);
      if (!drawerleftOpen) {
        mDrawerLayout.openDrawer(Gravity.START);
      } else {
        mDrawerLayout.closeDrawer(mleftList);
      }
      break;
    case R.id.action_insert:
      /*
       * Launches a new Activity using an Intent. The intent filter for the Activity has to have action ACTION_INSERT.
       * No category is set, so DEFAULT is assumed. In effect, this starts the NoteEditor Activity in NotePad.
       */
      startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
      break;

    case R.id.action_sign_out:
      for (Account account : accounts) {
        Log.i(TAG, "remove account : " + account.name);
        AccountManager.get(this).removeAccount(account, null, null);
      }

      Intent intent = new Intent(this, MainActivity.class);
      finish();
      Log.i(TAG, "Intent : " + intent.toString());
      startActivity(intent);

    case R.id.action_sync:
      accounts = AccountManager.get(this).getAccountsByType(Constant.ACCOUNT_TYPE);
      if (accounts.length == 0) {
        // Intent intent = new Intent(this, MainActivity.class);
        // startActivity(intent);
      }
      break;
    default:
      break;
    }

    return super.onOptionsItemSelected(item);
  }

  /**
   * This method is called when the user context-clicks a note in the list. NotesList registers itself as the handler
   * for context menus in its ListView (this is done in onCreate()). The only available options are COPY and DELETE.
   * Context-click is equivalent to long-press.
   *
   * @param menu A ContexMenu object to which items should be added.
   * @param v The View for which the context menu is being constructed.
   * @param menuInfo Data associated with view.
   * @throws ClassCastException
   */
  @Override
  public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    // The data from the menu item.
    AdapterView.AdapterContextMenuInfo info;

    // Tries to get the position of the item in the ListView that was
    // long-pressed.
    try {
      // Casts the incoming data object into the type for AdapterView
      // objects.
      info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    } catch (ClassCastException e) {
      // If the menu object can't be cast, logs an error.
      Log.e(TAG, "bad menuInfo", e);
      return;
    }

    /*
     * Gets the data associated with the item at the selected position. getItem() returns whatever the backing adapter
     * of the ListView has associated with the item. the adapter associated all of the data for a note with its list
     * item. As a result, getItem() returns that data as a Cursor.
     */
    Task task = tasks.get(info.position);

    // If the cursor is empty, then for some reason the adapter can't get
    // the data from the
    // provider, so returns null to the caller.
    if (task == null) {
      // For some reason the requested item isn't available, do nothing
      return;
    }

    // Inflate menu from XML resource
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.task_list_context, menu);

    // Sets the menu header to be the title of the selected note.
    menu.setHeaderTitle(task.getName());

    /*
     * Append to the menu items for any other activities that can do stuff with it as well. This does a query on the
     * system for any activities that implement the ALTERNATIVE_ACTION for our data, adding a menu item for each one
     * that is found.
     */
    Intent intent = new Intent(null, Uri.withAppendedPath(getIntent().getData(), Integer.toString(task.getId())));
    intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
    menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, new ComponentName(this, TaskListActivity.class), null,
        intent, 0, null);
  }

  /**
   * This method is called when the user selects an item from the context menu (see onCreateContextMenu()). The only
   * menu items that are actually handled are DELETE and COPY. Anything else is an alternative option, for which default
   * handling should be done.
   *
   * @param item The selected menu item
   * @return True if the menu item was DELETE, and no default processing is need, otherwise false, which triggers the
   *         default handling of the item.
   * @throws ClassCastException
   */
  @Override
  public boolean onContextItemSelected(MenuItem item) {
    // The data from the menu item.
    AdapterView.AdapterContextMenuInfo info;

    Task task;

    try {
      // Casts the data object in the item into the type for AdapterView
      // objects.
      info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
      // get info task
      task = tasks.get(info.position);
      if (task == null) {
        return false;
      }
    } catch (ClassCastException e) {

      // If the object can't be cast, logs an error
      Log.e(TAG, "bad menuInfo", e);

      // Triggers default processing of the menu item.
      return false;
    }
    // Appends the selected task's ID to the URI sent with the incoming
    // Intent.
    Uri taskUri = ContentUris.withAppendedId(getIntent().getData(), task.getId());

    /*
     * Gets the menu item's ID and compares it to known actions.
     */
    switch (item.getItemId()) {
    case R.id.context_edit:
      // Launch activity to view/edit the currently selected item
      startActivity(new Intent(Intent.ACTION_EDIT, taskUri));
      return true;

    case R.id.context_delete:

      /*
       * Deletes the note from the provider by passing in a URI in note ID format. Please see the introductory note
       * about performing provider operations on the UI thread.
       */
      getContentResolver().delete(taskUri, null, null);
      ToastUtils.toast(this, R.string.toast_msg_task_delete_success);
      updateData();

      // Returns to the caller and skips further processing.
      return true;
    default:
      return super.onContextItemSelected(item);
    }
  }

  /**
   * This method is called when the user clicks a task in the displayed list. This method handles incoming actions of
   * either PICK (get data from the provider) or GET_CONTENT (get or create data). If the incoming action is EDIT, this
   * method sends a new Intent to start NoteEditor.
   * 
   * @param l The ListView that contains the clicked item
   * @param v The View of the individual item
   * @param position The position of v in the displayed list
   * @param id The row ID of the clicked item
   */
  @Override
  protected void onListItemClick(ListView l, View v, int position, long id) {
    // get info task
    Task task = tasks.get(position);
    if (task == null) {
      return;
    }

    // Constructs a new URI from the incoming URI and the row ID
    Uri uri = ContentUris.withAppendedId(getIntent().getData(), task.getId());

    // Gets the action from the incoming Intent
    String action = getIntent().getAction();

    // Handles requests for note data
    if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) {

      /*
       * Sets the result to return to the component that called this Activity. The result contains the new URI
       */
      setResult(RESULT_OK, new Intent().setData(uri));
    } else {

      /*
       * Sends out an Intent to start an Activity that can handle ACTION_EDIT. The Intent's data is the task ID URI. The
       * effect is to call TaskEdit.
       */
      startActivity(new Intent(Intent.ACTION_EDIT, uri));
    }
  }

}
